#include "lcd_driver.h"
#include <Arduino.h>

#if 0
#define delayUsec(us)   delayMicroseconds(us)
#else
#define delayUsec(us)  
#endif


#define DB_NUM 16
/****************************************************
 * 变量
 * cs 片选
 * rs 命令/数据
 * rd 读
 * rw 写
 * db[DB_NUM] 数据
*/
static uint8_t _cs;
static uint8_t _rs;
static uint8_t _rd;
static uint8_t _wr;
static uint8_t _db[DB_NUM];



#define LOW_32(data, i)  ((data&0x0001<<i)>>i)<<_db[i]
#define HIGH_32(data, i)  ((data&0x0001<<i)>>i)<<(_db[i]-32)
#define LOW32_0(pin) (GPIO.out_w1tc = 1<<pin)		      //设置pin为0，pin<32
#define LOW32_1(pin) (GPIO.out_w1ts = 1<<pin)             //设置pin为1，pin<32
#define HIGH32_0(pin) (GPIO.out1_w1tc.val = 1<<(pin-32))  //设置pin为0，pin>=32
#define HIGH32_1(pin) (GPIO.out1_w1ts.val = 1<<(pin-32))  //设置pin为1，pin>=32

// 这里DB6,DB7,DB8的IO号大于32
// #define WRITE_DATA(data)  \
// 					GPIO.out_w1ts = ((data&0x0001)>>0)<<_db[0]| \
// 									((data&0x0002)>>1)<<_db[1]| \ 
// 									((data&0x0004)>>2)<<_db[2]| \
// 									((data&0x0008)>>3)<<_db[3]| \
// 									((data&0x0010)>>4)<<_db[4]| \
// 									((data&0x0020)>>5)<<_db[5]| \
// 									((data&0x0200)>>9)<<_db[9]| \
// 									((data&0x0400)>>10)<<_db[10]| \
// 									((data&0x0800)>>11)<<_db[11]| \
// 									((data&0x1000)>>12)<<_db[12]| \
// 									((data&0x2000)>>13)<<_db[13]| \
// 									((data&0x4000)>>14)<<_db[14]| \
// 									((data&0x8000)>>15)<<_db[15]; \        					
// 					GPIO.out1_w1ts.val = 	0x0000|					\
//											((data&0x0040)>>6)<<(_db[6]-32)| \
// 											((data&0x0080)>>7)<<(_db[7]-32)| \
// 											((data&0x0100)>>8)<<(_db[8]-32)
// #define CS_0 (GPIO.out_w1tc = 1<<_cs)
// #define CS_1 (GPIO.out_w1ts = 1<<_cs)
// #define RS_0 (GPIO.out_w1tc = 1<<_rs)
// #define RS_1 (GPIO.out_w1ts = 1<<_rs)
// #define WR_0 (GPIO.out_w1tc = 1<<_wr)
// #define WR_1 (GPIO.out_w1ts = 1<<_wr)

//这里需要根据情况修改
//配置中只有DB6,DB7,DB8的IO号大于32
#define WRITE_DATA(data)  \
					GPIO.out_w1ts = LOW_32(data,0)| \
									LOW_32(data,1)| \
									LOW_32(data,2)| \
									LOW_32(data,3)| \
									LOW_32(data,4)| \
									LOW_32(data,5)| \
									LOW_32(data,8)| \
									LOW_32(data,9)| \
									LOW_32(data,10)| \
									LOW_32(data,11)| \
									LOW_32(data,12)| \
									LOW_32(data,13)| \
									LOW_32(data,14)| \
									LOW_32(data,15) \
					;							\
					GPIO.out1_w1ts.val = 	0x0000|	\
											HIGH_32(data,6)| \
											HIGH_32(data,7)  \
				    
//根据情况修改
#define CS_0 LOW32_0(_cs)
#define CS_1 LOW32_1(_cs)
#define RS_0 LOW32_0(_rs)
#define RS_1 LOW32_1(_rs)
#define WR_0 LOW32_0(_wr)
#define WR_1 LOW32_1(_wr)
	
	






#define HIGH_S 1

#if HIGH_S
static uint32_t _lcd_data_pin;
static uint32_t _lcd_data1_pin;
#endif

/****************************************************************************
*函数名：TFT_GPIO_Config
*输  入：无
*输  出：无
*功  能：初始化TFT的IO口。
****************************************************************************/	  

static void TFT_GPIO_Config(uint8_t cs, uint8_t rs, uint8_t rd, uint8_t wr, 
                 uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
				 uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
				 uint8_t d8, uint8_t d9, uint8_t d10, uint8_t d11,
				 uint8_t d12, uint8_t d13, uint8_t d14, uint8_t d15)
{
	uint8_t i =0;
	_cs = cs;
    _rs = rs;
	_rd = rd;
    _wr = wr;
    _db[0] = d0;
	_db[1] = d1;
	_db[2] = d2;
	_db[3] = d3;
	_db[4] = d4;
	_db[5] = d5;
	_db[6] = d6;
	_db[7] = d7;
	_db[8] = d8;
	_db[9] = d9;
	_db[10] = d10;
	_db[11] = d11;
	_db[12] = d12;
	_db[13] = d13;
	_db[14] = d14;
	_db[15] = d15;
	   // 初始化io
   // ------------------------------------------
   for ( i = 0; i < DB_NUM; i++ )
   {
      pinMode( _db[i], OUTPUT );
	  digitalWrite(_db[i],1);
   }


#if HIGH_S
	_lcd_data_pin = 0;
	_lcd_data1_pin = 0;
	for(i=0;i<DB_NUM;i++)
	{
		if(_db[i]<32)
			_lcd_data_pin |= 0x0001<<_db[i];
		else
			_lcd_data1_pin |= 0x0001<<(_db[i]-32);
	}
#else

#endif
   
   pinMode(_cs, OUTPUT);
   digitalWrite(_cs,1);
   pinMode(_rs, OUTPUT);
   digitalWrite(_rs,1);
   pinMode(_rd, OUTPUT);
   digitalWrite(_rd,1);
   pinMode(_wr, OUTPUT);
   digitalWrite(_wr,1);

}

static void writeNbits(uint16_t value, uint8_t numBits) 
{
	
#if HIGH_S
    
#if 0     //速度比下面的慢

    
    uint64_t out=0;
    //将标志位清0
	//小于32
    GPIO.out_w1tc =_lcd_data_pin;
	//大于32
    GPIO.out1_w1tc.val =_lcd_data1_pin;

	


	#define CMD(i) (((((value&((uint64_t)0x01<<i))>>i)))<<_db[i])
	
	out = CMD(0)|CMD(1)|CMD(2)|CMD(3)|CMD(4)|CMD(5)|CMD(6)|CMD(7)|
		CMD(8)|CMD(9)|CMD(10)|CMD(11)|CMD(12)|CMD(13)|CMD(14)|CMD(15);

	#undef CMD

	GPIO.out_w1ts = out;
	GPIO.out1_w1ts.val = out >> 32;

	return;
#else
	
	//小于32
	//将标志位清0
    GPIO.out_w1tc =_lcd_data_pin;
	//大于32
	//将标志位清0
	GPIO.out1_w1tc.val =_lcd_data1_pin;

	//设置数据
	WRITE_DATA(value);

#endif
				
#else
	static uint16_t bef=0;
	if(bef==value)
	{
		return;
	}
	
	for (uint8_t i = 0; i < numBits; i++) 
	{
		digitalWrite(_db[i], (value >> i) & 0x01);
	}
   bef = value;
#endif
}

/****************************************************************************
* Function Name  : TFT_WriteCmd
* Description    : LCD写入命令
* Input          : cmd：写入的8位命令
* Output         : None
* Return         : None
****************************************************************************/
void TFT_WriteCmd(uint16_t cmd)
{
#if !HIGH_S
	//片选
	digitalWrite(_cs,0);
	
	//写指令
	digitalWrite(_rs,0);
	
	//写入拉低
	digitalWrite(_wr,0);
	
	//写入数据
	writeNbits(cmd,DB_NUM);
	delayUsec (1);
	//拉高写入
	digitalWrite(_wr,1);
	
	delayUsec (1);

	//还原
	digitalWrite(_cs,1);
	
	
#else 
    CS_0;
	RS_0;
	WR_0;
	writeNbits(cmd,DB_NUM);
	delayUsec (1);
	WR_1;
	CS_1;
#endif
}

/****************************************************************************
* Function Name  : TFT_WriteData
* Description    : LCD写入数据
* Input          : dat：写入的16位数据
* Output         : None
* Return         : None
****************************************************************************/

void TFT_WriteData(uint16_t dat)
{
#if !HIGH_S
	//片选
	digitalWrite(_cs,0);
	//写数据
	digitalWrite(_rs,1);
	//写入拉低
	digitalWrite(_wr,0);
	//写入数据
	writeNbits(dat,DB_NUM);
	delayUsec (1);
	//拉高写入
	digitalWrite(_wr,1);
	delayUsec (1);
	//还原
	digitalWrite(_cs,1);
#else
    CS_0;
	RS_1;
	WR_0;
	writeNbits(dat,DB_NUM);
	delayUsec (1);
	WR_1;
	CS_1;
#endif
}

/****************************************************************************
* Function Name  : TFT_Init
* Description    : 初始化LCD屏
* Input          : None
* Output         : None
* Return         : None
****************************************************************************/

void TFT_Init(uint8_t cs, uint8_t rs, uint8_t rd, uint8_t wr, 
                 uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
				 uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
				 uint8_t d8, uint8_t d9, uint8_t d10, uint8_t d11,
				 uint8_t d12, uint8_t d13, uint8_t d14, uint8_t d15)
{
	uint16_t i;

	TFT_GPIO_Config(cs, rs, rd, wr, d0, d1, d2, d3, d4, d5, d6, d7,d8, d9, d10, d11, d12, d13, d14, d15);

	TFT_WriteCmd(0xE9); 
	TFT_WriteData(0x20); 
	
	TFT_WriteCmd(0x11); //Exit Sleep 
	for(i=500; i>0; i--);
	
	TFT_WriteCmd(0x3A);
	TFT_WriteData(0x55);  //16Bit colors
	
	TFT_WriteCmd(0xD1); 
	TFT_WriteData(0x00); 
	TFT_WriteData(0x65); //调试此值改善水纹
	TFT_WriteData(0x1F); 
	
	TFT_WriteCmd(0xD0); 
	TFT_WriteData(0x07); 
	TFT_WriteData(0x07); 
	TFT_WriteData(0x80); 
	
	TFT_WriteCmd(0x36); 	 //Set_address_mode
	TFT_WriteData(0x48);   	//48
	
	TFT_WriteCmd(0xC1); 
	TFT_WriteData(0x10); 
	TFT_WriteData(0x10); 
	TFT_WriteData(0x02); 
	TFT_WriteData(0x02); 
	
	TFT_WriteCmd(0xC0); //Set Default Gamma 
	TFT_WriteData(0x00);  
	TFT_WriteData(0x35); 
	TFT_WriteData(0x00); 
	TFT_WriteData(0x00); 
	TFT_WriteData(0x01); 
	TFT_WriteData(0x02); 

	TFT_WriteCmd(0xC4);			
	TFT_WriteData(0x03);

	TFT_WriteCmd(0xC5); //Set frame rate 
	TFT_WriteData(0x01); 
	
	TFT_WriteCmd(0xD2); //power setting 
	TFT_WriteData(0x01); 
	TFT_WriteData(0x22); 

	TFT_WriteCmd(0xE7);			
	TFT_WriteData(0x38);
	
	TFT_WriteCmd(0xF3);			
    TFT_WriteData(0x08); 
	TFT_WriteData(0x12);
	TFT_WriteData(0x12);
	TFT_WriteData(0x08);

	TFT_WriteCmd(0xC8); //Set Gamma 
	TFT_WriteData(0x01); 
	TFT_WriteData(0x52); 
	TFT_WriteData(0x37); 
	TFT_WriteData(0x10); 
	TFT_WriteData(0x0d); 
	TFT_WriteData(0x01); 
	TFT_WriteData(0x04); 
	TFT_WriteData(0x51); 
	TFT_WriteData(0x77); 
	TFT_WriteData(0x01); 
	TFT_WriteData(0x01); 
	TFT_WriteData(0x0d); 
	TFT_WriteData(0x08); 
	TFT_WriteData(0x80); 
	TFT_WriteData(0x00);  

	TFT_WriteCmd(0x29); //display on

}

/****************************************************************************
* Function Name  : TFT_SetWindow
* Description    : 设置要操作的窗口范围
* Input          : xStart：窗口起始X坐标
*                * yStart：窗口起始Y坐标
*                * xEnd：窗口结束X坐标
*                * yEnd：窗口结束Y坐标
* Output         : None
* Return         : None
****************************************************************************/

void TFT_SetWindow(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd)
{
 	TFT_WriteCmd(0x2A);

    TFT_WriteData(xStart>>8);
    TFT_WriteData(xStart&0XFF);
    TFT_WriteData(xEnd>>8);
    TFT_WriteData(xEnd&0XFF);

    TFT_WriteCmd(0x2b);
    TFT_WriteData(yStart>>8);
    TFT_WriteData(yStart&0XFF);
    TFT_WriteData(yEnd>>8);
    TFT_WriteData(yEnd&0XFF);
    TFT_WriteCmd(0x2c); 
}

/****************************************************************************
* Function Name  : TFT_ClearScreen
* Description    : 将LCD清屏成相应的颜色
* Input          : color：清屏颜色
* Output         : None
* Return         : None
****************************************************************************/
	  
void TFT_ClearScreen(uint16_t color)
{
 	uint16_t i, j ;

	TFT_SetWindow(0, 0, TFT_XMAX, TFT_YMAX);	 //作用区域
  	for(i=0; i<TFT_XMAX+1; i++)
	{
		for (j=0; j<TFT_YMAX+1; j++)
		{
			
			TFT_WriteData(color);
		}
	}
}
